use http;
use http::{httprequest,httprequest::HttpRequest,httpresponse::HttpResponse,httprequest::Resource};
use serde::{Deserialize,Serialize};
use std::collections::HashMap;
use std::env;
use std::fs;

pub trait Handler{
    fn handler(req:&HttpRequest)->HttpResponse;
    fn load_file(file_name:&str)->Option<String>{
        let default_path=format!("{}/public",env!("CARGO_MANIFEST_DIR"));//crate 根目录
        let public_path=env::var("PUBLIC_PATH").unwrap_or(default_path);
        let full_path=format!("{}/{}",public_path,file_name);
        //返回 Result 类型
        let contents=fs::read_to_string(full_path);
        contents.ok()//。ok 返回正确值
    }
}

pub struct StaticPageHandler;
pub struct PageNotFoundHandler;
pub struct WebServiceHandler;

#[derive(Serialize,Deserialize)] //OrderStatus 需要实现序列化 反序列化
pub struct OrderStatus{
    order_id:i32,
    order_date:String,
    order_status:String,
}

//几个handler 实现handler trait
impl Handler for PageNotFoundHandler{
    fn handler(_req:&HttpRequest)->HttpResponse{
        //Self代表的 Handler trait
        HttpResponse::new("404",None,Self::load_file("404.html"))
    }
}

impl Handler for StaticPageHandler{
    fn handler(req:&HttpRequest)->HttpResponse{
        //获取资源-路径
        let http::httprequest::Resource::Path(s)=&req.resource;
        let route:Vec<_>=s.split("/").collect();//获得字符串数组
        match route[1]{
            ""=>HttpResponse::new("200",None,Self::load_file("index.html")),
            "health"=>HttpResponse::new("200",None,Self::load_file("health.html")),
            //route[1]是 其他字符串，是否正好对应一个文件
            path=>match Self::load_file(path){
                Some(contents)=>{
                    let mut map=HashMap::new();
                    if path.ends_with(".css"){
                        map.insert("Content-Type","text/css");
                    }else if path.ends_with(".js"){
                        map.insert("Content-Type","text/javascript");
                    }else{
                        map.insert("Content-Type","text/html");
                    }
                    //组成response 返回；map为Headers
                    HttpResponse::new("200",Some(map),Self::load_file(contents.as_str()))
                },
                None=>HttpResponse::new("404",None,Self::load_file("404.html"))
            },
        }
    }
}


impl WebServiceHandler{
    fn load_json()->Vec<OrderStatus>{
        let default_path=format!("{}/data",env!("CARGO_MANIFEST_DIR"));
        let data_path=env::var("DATA_PATH").unwrap_or(default_path);
        let full_path=format!("{}/{}",data_path,"orders.json");
        let json_content=fs::read_to_string(full_path);
        let orders:Vec<OrderStatus>=serde_json::from_str(json_content.unwrap().as_str()).unwrap();
        orders
    }
}

impl Handler for WebServiceHandler{
    fn handler(req:&HttpRequest)->HttpResponse{
        let http::httprequest::Resource::Path(s)=&req.resource;
        let route:Vec<&str>=s.split("/").collect();
        //localhost:3000/api/shipping/orders
        match route[2]{
            "shipping" if route.len() >2 && route[3]=="orders"=>{
                let body=Some(serde_json::to_string(&Self::load_json()).unwrap());
                let mut headers=HashMap::new();
                headers.insert("Content-Type","application/json");
                HttpResponse::new("200",Some(headers),body)
            }
            _=>HttpResponse::new("404",None,Self::load_file("404.html")),
        }
    }
}